package org.xxpay.pay.mq.queue;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.DateUtil;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.MchAccountHistory;
import org.xxpay.core.entity.MchAgentpayRecord;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.service.CommonService;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

@Component
public class MqQueue4Statistics {

    private static final MyLog _log = MyLog.getLog(MqQueue4Statistics.class);

    @Autowired
    private CommonService commonService;

    @Autowired
    private MqQueue4MchStatistics mchStatistics;

    @Autowired
    private MqQueue4PlatStatistics platStatistics;

    @Autowired
    private MqQueue4PayPassageStatistics payPassageStatistics;


    /**
     * 处理发送支付订单统计通知，商户、平台、支付通道统计全部发送
     * @param payOrder
     * @param orderStatus  0-下单  1-支付成功
     */
    public void sendPayStatistics(PayOrder payOrder, Byte orderStatus) {
        sendPayStatistics(payOrder, orderStatus, 0L);
    }

    /**
     * 处理发送支付订单统计通知，商户、平台、支付通道统计全部发送
     * @param payOrder
     * @param orderStatus  0-下单  1-支付成功
     * @param diffAmount  订单成功时，确认实付金额与原订单金额的差值
     */
    public void sendPayStatistics(PayOrder payOrder, Byte orderStatus, Long diffAmount) {
        _log.info(">>>>>> 发送支付订单统计通知,payOrderId：{}", payOrder.getPayOrderId());

        payOrder = commonService.payOrderService.findByPayOrderId(payOrder.getPayOrderId());
        // 生成通知统计数据
        JSONObject object = createPayStatisticsInfo(payOrder, orderStatus, diffAmount);
        object.put("orderId", payOrder.getPayOrderId());
        object.put("isNeedRemoveDup", true);//是否需要订单去重
        object.put("orderType", MchConstant.ORDER_TYPE_PAY);
        object.put("orderStatus", orderStatus);

        //发送通知
        send2all(object);
        _log.info(">>>>>> 发送支付订单统计通知完成  <<<<<<");
    }


    /**
     * 处理代付订单统计通知，商户、平台统计发送通知
     * @param record
     * @param orderStatus  0-下单  1-支付成功
     */
    public void sendAgentPayStatistics(MchAgentpayRecord record, Byte orderStatus) {
        sendAgentPayStatistics(record, orderStatus, true);
    }

    /**
     * 处理代付订单统计通知，商户、平台统计发送通知
     * @param record
     * @param orderStatus  0-下单  1-支付成功
     */
    public void sendAgentPayStatistics(MchAgentpayRecord record, Byte orderStatus, Boolean isNeedRemoveDup) {
        //查询最新记录
        record = commonService.mchAgentpayService.findByAgentpayOrderId(record.getAgentpayOrderId());
        sendAgentPayStatisticsBatch(Arrays.asList(record), orderStatus, isNeedRemoveDup);
    }


    /**
     * 处理批量代付订单统计通知，商户、平台统计发送通知
     * @param recordList
     * @param orderStatus  0-下单  1-支付成功
     */
    public void sendAgentPayStatisticsBatch(List<MchAgentpayRecord> recordList, Byte orderStatus, Boolean isNeedRemoveDup) {
        _log.info(">>>>>> 发送代付订单统计通知,List<MchAgentpayRecord>：{}", recordList);
        // 生成通知统计数据
        JSONObject object = createAgentPayStatisticsInfo(recordList, orderStatus);
        object.put("orderId", recordList.get(0).getAgentpayOrderId());
        object.put("isNeedRemoveDup", isNeedRemoveDup);//是否需要订单去重
        object.put("orderType", MchConstant.ORDER_TYPE_AGENTPAY);
        object.put("orderStatus", orderStatus);

        send2MchAndPlatStatistics(object);

        _log.info(">>>>>> 发送代付订单统计通知完成  <<<<<<");
    }

    /**
     * 处理代付订单统计通知，当代付状态由成功改为失败时，商户、平台统计发送通知
     * @param record
     */
    public void sendAgentPayStatisticsFail(MchAgentpayRecord record) {
        _log.info(">>>>>> 当代付状态由成功改为失败时，发送代付订单统计通知, mchAgentpayRecordId：{}", record.getAgentpayOrderId());
        //查询最新记录
        record = commonService.mchAgentpayService.findByAgentpayOrderId(record.getAgentpayOrderId());

        JSONObject object = new JSONObject();
        object.put("isNeedRemoveDup", false);//是否需要订单去重
        object.put("orderType", MchConstant.ORDER_TYPE_AGENTPAY);
        object.put("orderStatus", MchConstant.ORDER_STATUS_SUCCESS);
        object.put("mchId", record.getMchId());
        object.put("statisticsDate", DateUtil.dateTime2date(record.getCreateTime()));

        if (record.getStatus() == PayConstant.AGENTPAY_STATUS_FAIL) {//代付失败
            object.put("successCount", -1);
            object.put("successAmount", 0 - record.getAmount());//代付金额
            object.put("fee", 0 - record.getFee());//手续费

            MchAccountHistory history = commonService.mchAccountHistoryService.findByOrderId(record.getAgentpayOrderId());
            object.put("profit", 0 - history.getPlatProfit());//平台分润
        }
        doJSONObjectEmpty(object);

        send2MchAndPlatStatistics(object);

        _log.info(">>>>>> 当代付状态由成功改为失败时，发送代付订单统计通知完成  <<<<<<");
    }


    /**
     * 处理发送代付充值成功统计通知，商户、平台统计发送通知
     * @param record
     * @param rechargeType  0-平台给商户代充   1-审核商户线下充值
     */
    public void sendRechargeStatisticsSuccess(MchAccountHistory record, Byte rechargeType) {
        _log.info(">>>>>> 发送代付充值成功统计通知,mchAccountHistory：{}", record);
        record = commonService.mchAccountHistoryService.findById(record.getId());
        // 生成通知统计数据
        JSONObject object = createRechargeStatisticsSuccessInfo(record, rechargeType);
        object.put("isNeedRemoveDup", false);//是否需要订单去重
        object.put("orderType", MchConstant.ORDER_TYPE_RECHARGE);
        object.put("orderStatus", MchConstant.ORDER_STATUS_SUCCESS);
        object.put("rechargeType", rechargeType);

        send2MchAndPlatStatistics(object);
        _log.info(">>>>>> 发送代付充值成功统计通知完成  <<<<<<");
    }


    /** 支付订单，推送消息到商户、平台、支付通道统计 **/
    public void send2all(JSONObject object) {
        mchStatistics.send(object);
        platStatistics.send(object);
        payPassageStatistics.send(object);
    }

    /** 推送消息到商户、平台统计 **/
    public void send2MchAndPlatStatistics(JSONObject object) {
        mchStatistics.send(object);
        platStatistics.send(object);
    }


    /** 支付通知数据 **/
    private JSONObject createPayStatisticsInfo(PayOrder payOrder, Byte orderStatus, Long diffAmount) {
        JSONObject object = new JSONObject();
        object.put("mchId", payOrder.getMchId());
        object.put("payPassageId", payOrder.getPassageId());
        object.put("payPassageAccountId", payOrder.getPassageAccountId());
        object.put("statisticsDate", DateUtil.dateTime2date(payOrder.getCreateTime()));

        if (orderStatus == MchConstant.ORDER_STATUS_INIT) {//初始下单
            object.put("totalCount", 1);
            object.put("totalAmount", payOrder.getAmount());
        } else if (orderStatus == MchConstant.ORDER_STATUS_SUCCESS &&
                (payOrder.getStatus() == PayConstant.PAY_STATUS_SUCCESS || payOrder.getStatus() == PayConstant.PAY_STATUS_COMPLETE)) {//支付成功
            object.put("totalAmount", diffAmount);
            object.put("successCount", 1);
            object.put("successAmount", payOrder.getAmount());
            object.put("fee", payOrder.getAmount() - payOrder.getMchIncome());//商户手续费
            object.put("profit", payOrder.getPlatProfit());//平台利润
            object.put("channelCost", payOrder.getChannelCost());//通道成本
        }

        doJSONObjectEmpty(object);

        return object;
    }

    /** 代付通知数据 **/
    private JSONObject createAgentPayStatisticsInfo(List<MchAgentpayRecord> recordList, Byte orderStatus) {

        List<String> idList = new LinkedList();
        for (MchAgentpayRecord record : recordList) {
            idList.add(record.getAgentpayOrderId());
        }
        recordList = commonService.mchAgentpayService.selectList(idList);

        JSONObject object = new JSONObject();
        object.put("mchId", recordList.get(0).getMchId());
        object.put("statisticsDate", DateUtil.dateTime2date(recordList.get(0).getCreateTime()));

        Long amount = 0L;//总代付金额
        Long fee = 0L;//总手续费
        boolean recordStatus = true;
        for (MchAgentpayRecord record : recordList) {
            amount += record.getAmount();
            fee += record.getFee();

            if (record.getStatus() != PayConstant.AGENTPAY_STATUS_SUCCESS) {
                recordStatus = false;
            }
        }

        if (orderStatus == MchConstant.ORDER_STATUS_INIT) {//初始下单
            object.put("totalCount", recordList.size());
            object.put("totalAmount", amount);
        } else if (orderStatus == MchConstant.ORDER_STATUS_SUCCESS && recordStatus) {//代付成功
            object.put("successCount", recordList.size());
            object.put("successAmount", amount);
            object.put("fee", fee);//手续费

            Long profit = 0L;//平台总分润
            List<MchAccountHistory> historyList = commonService.mchAccountHistoryService.selectList(idList);
            for (MchAccountHistory history : historyList) {
                profit += history.getPlatProfit();
            }
            object.put("profit", profit);
        }

        doJSONObjectEmpty(object);

        return object;
    }

    /** 充值成功通知数据  rechargeType  0-平台给商户代充   1-商户发起线下充值 **/
    private JSONObject createRechargeStatisticsSuccessInfo(MchAccountHistory record, Byte rechargeType) {
        JSONObject object = new JSONObject();
        object.put("mchId", record.getMchId());
        object.put("successCount", 1);
        object.put("successAmount", record.getOrderAmount());
        object.put("fee", record.getFee());//手续费
        object.put("profit", record.getPlatProfit());//平台利润

        if (rechargeType == 0) {
            object.put("statisticsDate", DateUtil.dateTime2date(record.getCreateTime()));
            object.put("totalCount", 1);
            object.put("totalAmount", record.getOrderAmount());
        }

        doJSONObjectEmpty(object);

        return object;
    }


    private JSONObject doJSONObjectEmpty(JSONObject object) {
        if(object == null) return object;
        if(null == object.getInteger("totalCount")) object.put("totalCount", 0);
        if(null == object.getLong("totalAmount")) object.put("totalAmount", 0);
        if(null == object.getInteger("successCount")) object.put("successCount", 0);
        if(null == object.getLong("successAmount")) object.put("successAmount", 0);
        if(null == object.getLong("fee")) object.put("fee", 0);
        if(null == object.getLong("profit")) object.put("profit", 0);
        if(null == object.getLong("channelCost")) object.put("channelCost", 0);
        return object;
    }

}
